package com.atguigu.daijia.driver.service.impl;

import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.driver.config.TencentCloudProperties;
import com.atguigu.daijia.driver.service.CosService;
import com.atguigu.daijia.driver.service.OcrService;
import com.atguigu.daijia.model.vo.driver.CosUploadVo;
import com.atguigu.daijia.model.vo.driver.DriverLicenseOcrVo;
import com.atguigu.daijia.model.vo.driver.IdCardOcrVo;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.ocr.v20181119.OcrClient;
import com.tencentcloudapi.ocr.v20181119.models.DriverLicenseOCRRequest;
import com.tencentcloudapi.ocr.v20181119.models.DriverLicenseOCRResponse;
import com.tencentcloudapi.ocr.v20181119.models.IDCardOCRRequest;
import com.tencentcloudapi.ocr.v20181119.models.IDCardOCRResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.Objects;


@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OcrServiceImpl implements OcrService {
    @Autowired
    private TencentCloudProperties tencentCloudProperties;

    @Autowired
    private CosService cosService;

    /**
     * 对上传的身份证图片进行ocr识别
     *
     * @param file
     * @return
     */
    @Override
    public IdCardOcrVo idCardOcr(MultipartFile file) {
        try {
            log.info("将图片文件转化为 base64格式 方便调ocr接口");
            byte[] bytes = Base64.encodeBase64(file.getBytes());
            String fileBase64 = new String(bytes);
            log.info("实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密");
            Credential cred = new Credential(tencentCloudProperties.getSecretId(), tencentCloudProperties.getSecretKey());
            log.info(" 实例化一个http选项，可选的，没有特殊需求可以跳过");
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
            log.info("实例化一个client选项，可选的，没有特殊需求可以跳过");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            log.info("实例化要请求产品的client对象，clientProfile是可选的 ,这是发请求的客户端对象");
            OcrClient client = new OcrClient(cred, tencentCloudProperties.getRegion(), clientProfile);
            log.info("实例化一个请求对象,每个接口都会对应一个request对象");
            IDCardOCRRequest req = new IDCardOCRRequest();
            log.info("给请求对象 设置  要进行ocr 的 文件");
            req.setImageBase64(fileBase64);
            // TODO 这里有个问题，在调ocr接口的时候要设置图片参数是正面还是背面, 所以前端在上传图片的时候 就要标识出来这张图是正面还是背面 ,但是前端没传，为了方便测试这里把背面的图片后缀改成了jpeg
            String subFix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
            req.setCardSide(subFix.contains("jpeg")?"BACK":"FRONT");
            log.info("返回的resp是一个IDCardOCRResponse的实例，与请求对象对应");
            IDCardOCRResponse resp = client.IDCardOCR(req);
            log.info("转换为IdCardOcrVo对象");
            IdCardOcrVo idCardOcrVo = new IdCardOcrVo();
            if (StringUtils.hasText(resp.getName())) {
                log.info("如果响应体 name字段有值， 说明是身份证 正面");
                idCardOcrVo.setName(resp.getName());
                idCardOcrVo.setGender("男".equals(resp.getSex()) ? "1" : "2");
                idCardOcrVo.setBirthday(DateTimeFormat.forPattern("yyyy/MM/dd").parseDateTime(resp.getBirth()).toDate());
                idCardOcrVo.setIdcardNo(resp.getIdNum());
                idCardOcrVo.setIdcardAddress(resp.getAddress());

                log.info("上传身份证正面图片到腾讯云cos");
                CosUploadVo cosUploadVo = cosService.upload(file, "idCard");
                idCardOcrVo.setIdcardFrontUrl(cosUploadVo.getUrl());
                idCardOcrVo.setIdcardFrontShowUrl(cosUploadVo.getShowUrl());
            } else {
                log.info("如果响应体 name字段没有值， 说明是身份证 反面");
                //证件有效期："2010.07.21-2020.07.21"
                log.info("按- 短横线 分割 开始时间和结束时间");
                String idcardExpireString = resp.getValidDate().split("-")[1];
                idCardOcrVo.setIdcardExpire(DateTimeFormat.forPattern("yyyy.MM.dd").parseDateTime(idcardExpireString).toDate());
                log.info("上传身份证到腾讯云");
                CosUploadVo cosUploadVo = cosService.upload(file, "idCard");
                idCardOcrVo.setIdcardBackUrl(cosUploadVo.getUrl());
                idCardOcrVo.setIdcardBackShowUrl(cosUploadVo.getShowUrl());
            }
            return idCardOcrVo;

        } catch (Exception e) {
            e.printStackTrace();
            throw new GuiguException(ResultCodeEnum.TENCENT_CLOUD_ERROR);
        }
    }

    /**
     * 驾驶证识别
     */

    @Override
    public DriverLicenseOcrVo driverLicenseOcr(MultipartFile file) {
        try{
            log.info("图片转换base64格式字符串");
            byte[] base64 = Base64.encodeBase64(file.getBytes());
            String fileBase64 = new String(base64);
            log.info("实例化一个认证对象，入参需要传入腾讯云账户 SecretId 和 SecretKey，此处还需注意密钥对的保密");
            Credential cred = new Credential(tencentCloudProperties.getSecretId(),tencentCloudProperties.getSecretKey());
            log.info("实例化一个http选项，可选的，没有特殊需求可以跳过");
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("ocr.tencentcloudapi.com");
            log.info("实例化一个client选项，可选的，没有特殊需求可以跳过");
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            log.info("实例化要请求产品的client对象,clientProfile是可选的");
            OcrClient client = new OcrClient(cred, tencentCloudProperties.getRegion(),
                    clientProfile);
            log.info("实例化一个请求对象,每个接口都会对应一个request对象");
            DriverLicenseOCRRequest req = new DriverLicenseOCRRequest();
            req.setImageBase64(fileBase64);

            log.info("发送请求调用OCR，返回的resp是一个DriverLicenseOCRResponse的实例，与请求对象对应");
            DriverLicenseOCRResponse resp = client.DriverLicenseOCR(req);

            log.info("封装到vo对象里面");
            DriverLicenseOcrVo driverLicenseOcrVo = new DriverLicenseOcrVo();
            if (StringUtils.hasText(resp.getName())) {
                log.info("返回的resp里有名字 表示他是驾驶证正面");
                //驾驶证名称要与身份证名称一致
                driverLicenseOcrVo.setName(resp.getName());
                driverLicenseOcrVo.setDriverLicenseClazz(resp.getClass_());
                driverLicenseOcrVo.setDriverLicenseNo(resp.getCardCode());
                driverLicenseOcrVo.setDriverLicenseIssueDate(DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(resp.getDateOfFirstIssue()).toDate());
                driverLicenseOcrVo.setDriverLicenseExpire(DateTimeFormat.forPattern("yyyy-MM-dd").parseDateTime(resp.getEndDate()).toDate());

                log.info("上传驾驶证正面图片到腾讯云cos");
                CosUploadVo cosUploadVo = cosService.upload(file, "driverLicense");
                driverLicenseOcrVo.setDriverLicenseFrontUrl(cosUploadVo.getUrl());
                driverLicenseOcrVo.setDriverLicenseFrontShowUrl(cosUploadVo.getShowUrl());
            } else {
                log.info("返回的resp里没有名字 表示他是驾驶证反面");
                log.info("上传驾驶证反面图片到腾讯云cos");
                CosUploadVo cosUploadVo =  cosService.upload(file, "driverLicense");
                driverLicenseOcrVo.setDriverLicenseBackUrl(cosUploadVo.getUrl());
                driverLicenseOcrVo.setDriverLicenseBackShowUrl(cosUploadVo.getShowUrl());
            }

            return driverLicenseOcrVo;
        } catch (Exception e) {
            e.printStackTrace();
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }
    }
}
